﻿using System;

using mpu = Microsoft.Practices.Unity;
using mpuu = Microsoft.Practices.Unity.Utility;
using UnityConfiguration.Properties;
using System.Globalization;

namespace UnityConfiguration.Infrastructure
{
    internal static class InjectionParameterValueHelper
    {
        public static mpu.InjectionParameterValue CreateParameterValue(
            string typeName,
            string genericParameterName,
            InjectionParameterValue valueElement,
            UnityTypeResolver typeResolver)
        {
            string genericParameter;
            bool isGenericParameterArray;
            ExtractGenericParameter(genericParameterName, out genericParameter, out isGenericParameterArray);

            if (!string.IsNullOrEmpty(genericParameter))
            {
                if (!isGenericParameterArray)
                {
                    if (valueElement == null)
                    {
                        return new mpu.GenericParameter(genericParameter);
                    }
                    else
                    {
                        Dependency dependencyElement = valueElement as Dependency;
                        if (dependencyElement != null)
                        {
                            if (!string.IsNullOrEmpty(dependencyElement.Name))
                            {
                                return new mpu.GenericParameter(genericParameter, dependencyElement.Name);
                            }
                            else
                            {
                                return new mpu.GenericParameter(genericParameter);
                            }
                        }
                        else
                        {
                            // should not happen - checked during config deserialization
                            throw new InvalidOperationException(Resources.InvalidConfiguration);
                        }
                    }
                }
                else
                {
                    if (valueElement == null)
                    {
                        return new mpu.GenericResolvedArrayParameter(genericParameter);
                    }
                    else
                    {
                        Array arrayElement = valueElement as Array;
                        if (arrayElement != null)
                        {
                            return arrayElement.CreateParameterValue(genericParameter);
                        }
                        else
                        {
                            // should not happen - checked during config deserialization
                            throw new InvalidOperationException(Resources.InvalidConfiguration);
                        }
                    }
                }
            }
            else
            {
                if (valueElement == null)
                {
                    valueElement = new Dependency();
                }
                valueElement.TypeResolver = typeResolver;
                return valueElement.CreateParameterValue(typeResolver.ResolveType(typeName));
            }
        }

        private static void ExtractGenericParameter(
            string genericParameterName,
            out string genericParameter,
            out bool isGenericParameterArray)
        {
            genericParameter = genericParameterName;
            isGenericParameterArray = false;

            if (genericParameter != null)
            {
                if (genericParameter.EndsWith("[]", StringComparison.Ordinal))
                {
                    genericParameter = genericParameter.Substring(0, genericParameter.Length - 2);
                    isGenericParameterArray = true;
                }
            }
        }

        public static void GuardOnlyOneValue(InjectionParameterValue valueElement, string name)
        {
            if (valueElement != null)
            {
                throw new InvalidOperationException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.OnlyOneValueElementAllowed,
                        name));
            }
        }

        public static void GuardNotGeneric(string genericParameterName, string name)
        {
            if (!string.IsNullOrEmpty(genericParameterName))
            {
                throw new Exception(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.GenericParameterNotSupported,
                        genericParameterName,           /* the invalid parameter's name */
                        name)   /* the invalid value element's name */
                    );
            }
        }

        public static void GuardNotGenericArray(bool isGenericParameterArray, string genericParameterName, string name)
        {
            if (isGenericParameterArray)
            {
                throw new Exception(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.GenericParameterArrayNotSupported,
                        genericParameterName,           /* the invalid parameter's name */
                        name)   /* the invalid value element's name */
                    );
            }
        }
    }
}
